package com.ansion.commonchat.contact.systemcontact;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.text.TextUtils;

import androidx.core.content.ContextCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import com.ansion.commonchat.BaseApplication;
import com.ansion.commonchat.dao.CocoDaoBroadcastUtil;
import com.ansion.constant.BConstant;
import com.ansion.log.VLog;
import com.ansion.utils.ApplicationHelper;
import com.ansion.utils.CocoLocalBroadcastUtil;
import com.ansion.utils.CommonUtil;
import com.ansion.utils.ContactUtil;
import com.ansion.utils.permission.RealRxPermission;
import com.ansion.utils.thread.AbstractTaskThreadLimitCount;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;


public class AndroidContactsFactory {
    public static final String CONTACT_LOAD_FAIL = "CONTACT_LOAD_FAIL";
    private static AtomicBoolean needLoadContactOnResume = new AtomicBoolean();
    public static final String TAG = AndroidContactsFactory.class.getSimpleName();

    private static HashMap<Integer, AndroidContactDB> mAllContacts = new HashMap<Integer, AndroidContactDB>();

//    private static final Map<String, AndroidContactDB> mContactMD5PhoneDataMap = new ConcurrentHashMap<String, AndroidContactDB>();

    private static final Map<String, AndroidContactDB> mContactOrigalPhoneDataMap = new ConcurrentHashMap<String, AndroidContactDB>();

    private static final Map<String, AndroidContactDB> mContactPhoneDataMap = new ConcurrentHashMap<String, AndroidContactDB>();


    private static final Map<String, String> mContactPhoneNameMap = new ConcurrentHashMap<String, String>();

    private static final List<Integer> mSortedIds = new LinkedList<Integer>();

    private static final AtomicBoolean mHasLoadContacts = new AtomicBoolean(false);

    public static Map<Integer, AndroidContactDB> getAllContacts() {
            return getAllContacts(false);
    }

    public static HashSet<AndroidContactDB> getAllContactsSet() {
    	return new HashSet<AndroidContactDB>(getAllContacts(false).values());
    }

    public static Map<Integer, AndroidContactDB> getAllContacts(boolean reload) {

    	HashMap<Integer, AndroidContactDB> retMap=new HashMap<Integer, AndroidContactDB>();

        synchronized (mHasLoadContacts) {

            try {
                //mawenqiang 注释 size为0，不代表没有load完联系人
//                if (!mHasLoadContacts.get() || reload || mAllContacts.size() == 0) {
                if (!mHasLoadContacts.get() || reload /*|| mAllContacts.size() == 0*/) {

                    mHasLoadContacts.set(false);

                    long time=System.currentTimeMillis();

                    HashMap<Integer, AndroidContactDB> newContacts = AndroidCotactsFactory_2_0.getAllContacts();
                    if(newContacts == null || newContacts.isEmpty()){
                        needLoadContactOnResume.set(true);
                        CocoLocalBroadcastUtil.sendLocalBroadcast(new Intent(CONTACT_LOAD_FAIL));
                    }else{
                        needLoadContactOnResume.set(false);
                    }
                    Intent intent = new Intent(CocoDaoBroadcastUtil.kDAOAction_SystemCallAndSmsModel);
                    LocalBroadcastManager.getInstance(ApplicationHelper.getContext())
                            .sendBroadcast(intent);

                    clearData();
                    mAllContacts = newContacts;
                    if (!CommonUtil.isEmpty(mAllContacts)) {
                    	 	AndroidCotactsFactory_2_0.getSortedIds(mSortedIds, mAllContacts);
					}

                    VLog.i(TAG, "AndroidCotactsFactory_2_0 loadcontact cost--"+(System.currentTimeMillis()-time));
                    VLog.i(TAG, "AndroidCotactsFactory_2_0 loadcontact mAllContacts.size--"+mAllContacts.size());

                    phoneAndEmailMapping(mAllContacts);
                    mHasLoadContacts.set(true);
                }

                retMap= (HashMap<Integer, AndroidContactDB>) mAllContacts.clone();
            } catch (Exception e) {
                VLog.e(TAG, e);
                mHasLoadContacts.set(false);
            }
        }
        return retMap;
    }

    /**
     *
     * @param contactId
     * @return 返回contactId在通讯录中Index
     */
    public static int getContactIdIndex(int contactId){
    		return mSortedIds.indexOf(contactId);
    }

    private static void phoneAndEmailMapping(Map<Integer, AndroidContactDB> allContacts) {
        Iterator<Map.Entry<Integer, AndroidContactDB>> iter = allContacts.entrySet().iterator();

        while (iter.hasNext()) {
            Map.Entry<Integer, AndroidContactDB> entry = iter.next();
            AndroidContactDB contact = entry.getValue();
            // if (contact.getName() == null) {
            // continue;
            // }

            Set<String> phones = contact.getPhones();
//            Set<String> emails = contact.getEmails();
            for (String phone : phones) {
                if (TextUtils.isEmpty(phone))
                    continue;


                mContactOrigalPhoneDataMap.put(contact.getOriginalPhone(phone), contact);

                mContactPhoneNameMap.put(contact.getOriginalPhone(phone), contact.getName());

                mContactPhoneDataMap.put(phone, contact);
            }
        }
    }



    public static AndroidContactDB getContactByContactId(Integer contactId) {
        synchronized (mHasLoadContacts) {
            return mAllContacts.get(contactId);
        }
    }


    public static Map<String, String> getContactPhoneNameMap() {
        synchronized (mHasLoadContacts) {
            return new ConcurrentHashMap<String, String>(mContactPhoneNameMap);
        }
    }

    public static Map<String, AndroidContactDB> getContactPhoneDataMap() {
        synchronized (mHasLoadContacts) {
            return new ConcurrentHashMap<String, AndroidContactDB>(mContactPhoneDataMap);
        }
    }

    public static void startContactQuery() {
        AndroidContactLoadThread.getInstance().startQuery();
    }


    public static List<Integer> getSortedIds() {
        synchronized (mHasLoadContacts) {
            return new LinkedList<Integer>(mSortedIds);
        }
    }

    public static boolean hasAllowReadContacts() {
        return true;
    }





    public static void clear() {
        mHasLoadContacts.set(false);
        clearData();
        AndroidCotactsFactory_2_0.unRegisterContactsContentObserver();
    }

    public static void clearData() {
        mAllContacts.clear();
//        mContactMD5PhoneDataMap.clear();
        mContactOrigalPhoneDataMap.clear();
        mContactPhoneDataMap.clear();
//        mContactEmailDataMap.clear();
        mContactPhoneNameMap.clear();
        mSortedIds.clear();
    }

    public static void checkLoadContactOnResume(){
        if(needLoadContactOnResume.get()){
            needLoadContactOnResume.set(false);
            VLog.i("AndroidContactsFactory", "checkLoadContactOnResume");
            AndroidContactLoadThread.getInstance().startQuery();
        }
    }

    public static void forceLoadContact(){
        needLoadContactOnResume.set(false);
        VLog.i("AndroidContactsFactory", "checkLoadContactOnResume");
        AndroidContactLoadThread.getInstance().startQuery();
    }

    public static boolean ifInstantRetryWhenFail() {
        // 重新计算时间周期
        AndroidContactLoadThread.getInstance().refreshLoopLimit();
        // 在当前周期（30分钟）内，如果上传通讯录的次数小于，允许立即重试
        return AndroidContactLoadThread.getInstance().getLoopCount() < 30;
    }
}

class AndroidContactsObserver extends ContentObserver {

    public AndroidContactsObserver() {
        super(null);
    }

    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        VLog.i("TAG_CONTACT_UPLOAD", "contact ContentObserver onChange no uri");
        AndroidContactLoadThread.getInstance().startQuery();
//        SmsHelper.clearContactAvatarCache();

    }

}
class AndroidContactLoadThread extends AbstractTaskThreadLimitCount {
    private static AndroidContactLoadThread mAndroidContactLoadThread;
    private AndroidContactLoadThread(){}

    static AndroidContactLoadThread getInstance(){
        synchronized (AndroidContactLoadThread.class){
            if(null == mAndroidContactLoadThread){
                mAndroidContactLoadThread = new AndroidContactLoadThread();
                mAndroidContactLoadThread.setRefreshInterval(1 * 1000); // 默认设置一秒保证新应用启动速度
                mAndroidContactLoadThread.setTimeResetLoop(30 * 60 * 1000); // reset count each 30 min
                mAndroidContactLoadThread.setTimeWaitAfterOverlimit(60 * 1000); // sleep 60s if reach loop count (origin 1h)
            }
        }
        return mAndroidContactLoadThread;
    }
    @Override
    protected boolean loadData() {
        if( AndroidContactLoadThread.getInstance().getLoopCount() > 10) {
            mAndroidContactLoadThread.setRefreshInterval(5 * 1000); // minimal wait between loadData (origin 1s)
        }


        if (ContextCompat.checkSelfPermission(BaseApplication.getContext(), Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
            return false;
        }
        VLog.d("TAG_CONTACT", "loadData");
        AndroidContactsFactory.getAllContacts(true);
        CocoLocalBroadcastUtil.sendLocalBroadcast(new Intent(BConstant.FriendAction.ACTION_READCONTACT_END));
        return true;
    }

    public synchronized void startQuery() {
        ContactUtil.contactsPermissionChecked = RealRxPermission.getInstance().isGranted(Manifest.permission.READ_CONTACTS);
        if (ContactUtil.contactsPermissionChecked) {
            notifyQuery(false);
            VLog.d("TAG_CONTACT", "startQuery");
        } else {
            VLog.d("TAG_CONTACT", "startQuery no permission");
        }
    }

}
